做完了端點,接下來會把功能部分完成。
這邊會新增一個BookDetailSerializer
,在其中除了包含BookSerilizer
中的欄位外還會將description
的欄位加入,因此獨立做一個 serializer 出來。到 book/serializer.py 中新增:
# ...
class BookDetailSerializer(BookSerializer):
"""Serializer for book detail view."""
class Meta(BookSerializer.Meta):
fields = BookSerializer.Meta.fields + ['description']
這邊直接繼承自 BookSerializer,而class Meta
也同樣繼承自 BookSerializer。
class Meta
的繼承語法比較特別,需要注意。
儲存後到 book/views.py 中修改原本的程式碼並新增:
# ...
class BookViewSet(viewsets.ModelViewSet):
"""View for manage book APIs."""
serializer_class = serializers.BookDetailSerializer # 這邊改為 BookDetailSerializer
queryset = Book.objects.all()
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
# ...
def get_serializer_class(self):
"""Return the serializer class for request."""
if self.action == 'list':
return serializers.BookSerializer
return self.serializer_class
此處的函式會覆寫原本存在於ModelViewSet
中的預設函式,並將預設的serializer_class
設定為 BookDetailSerializer,因大多操作(如 create, update, delete)都會使用到 Book model 的所有欄位;而當 action 為 list 時才會使用BookSerializer
,也就會回傳不包含 description 的所有 Book list。延伸閱讀
除了這個函式之外,創建的函式也需要被覆寫,因為我們想讓創建物件的 user 與 object 產生關聯,而原本預設的創建函式沒有此設定。在BookViewSet
的下方再加入此函式:
# ...
class BookViewSet(viewsets.ModelViewSet):
# ...
def perform_create(self, serializer):
"""Create a new book."""
serializer.save(user=self.request.user)
以下幾種情況可能會需要像上面一樣製作另一個獨立的 serializer:
完成後,可以再次啟動伺服器測試看看,所有的端點應該都能回傳正確的回應。
這邊請求的
Request body
使用application/json
。
如此一來,目前 books API 端點的功能都完成了。在製作只有使用 CRUD 的 API 時使用 viewset 搭配 DefaultRouter 是個相當方便快速的工具。接下來會著手製作圖片的上傳功能,明天見~